package gang.org.springframework.framework.annotation;

import gang.org.springframework.framework.bean.GangBeanDefinition;
import gang.org.springframework.framework.bean.GangBeanDefinitionHolder;
import gang.org.springframework.framework.bean.GangRootBeanDefinition;
import gang.org.springframework.framework.beanfactorypostprocessor.GangConfigurationClassPostProcessor;
import gang.org.springframework.framework.beanpostprocessor.GangAutowiredAnnotationBeanPostProcessor;
import gang.org.springframework.framework.factory.GangDefaultListableBeanFactory;
import gang.org.springframework.framework.metadata.GangAnnotationAttributes;
import gang.org.springframework.framework.metadata.GangAnnotationMetadata;
import gang.org.springframework.framework.support.GangBeanDefinitionRegistry;

import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author gang.chen
 * @descriptionÏ
 * @Date 2021/6/13 18:18
 */
public abstract class GangAnnotationConfigUtils {

    public static final String CONFIGURATION_ANNOTATION_PROCESSOR_NAME="gang.org.springframework.framework.annotation.internalConfigurationAnnotationProcessor";

    public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME="gang.org.springframework.framework.annotation.internalAutowiredAnnotationProcessor";

    public static void registerAnnotationConfigProcessors(GangBeanDefinitionRegistry registry){
        registerAnnotationConfigProcessors(registry,null);
    }


    /**
     * 业务意义 TODO
     * 1）发生的时间：创建上下文时
     * 2）
     * @param registry {@link GangDefaultListableBeanFactory}
     * 1，GangConfigurationClassPostProcessor -> BeanFactoryPostProcess -> 封装GangRootBeanDefinition ->存储在Map
     *
     * */
    public static Set<GangBeanDefinitionHolder> registerAnnotationConfigProcessors(GangBeanDefinitionRegistry registry,Object source){
        Set<GangBeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_NAME)) {
            GangRootBeanDefinition def = new GangRootBeanDefinition(GangConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry,def,CONFIGURATION_ANNOTATION_PROCESSOR_NAME));
        }
        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            GangRootBeanDefinition def = new GangRootBeanDefinition(GangAutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry,def,AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        return beanDefs;
    }

    private static GangDefaultListableBeanFactory unwrapDefaultListableBeanFactory(GangBeanDefinitionRegistry registry){
        //return ((GangGenericApplicationContext)registry).getBeanFactory();
        return null;
    }

    private static GangBeanDefinitionHolder registerPostProcessor(GangBeanDefinitionRegistry registry, GangRootBeanDefinition definition,String beanName){
        definition.setRole(GangBeanDefinition.ROLE_INFRASTRUCTURE);
        registry.registerBeanDefinition(beanName,definition);
        return new GangBeanDefinitionHolder(definition,beanName);
    }

    /**
     * Repeatable 可重复的
     * @param metadata -> StandardAnnotationMetadata 标准注解元数据
     * @param containerClass -> GComponentScan（gang.org.springframework.framework.annotation.GComponentScans）
     * @param annotationClass -> GComponentScan（gang.org.springframework.framework.annotation.GComponentScan）
     * */
    public static Set<GangAnnotationAttributes> attributesForRepeatable(GangAnnotationMetadata metadata, Class<?> containerClass, Class<?> annotationClass){
        return attributesForRepeatable(metadata, containerClass.getName(), annotationClass.getName());
    }

    /**
     * @param metadata 元数据 -> StandardAnnotationMetadata
     * @param annotationClassName 注解类名 -> gang.org.springframework.framework.annotation.GComponentScans
     * @param containerClassName 注解类名 -> gang.org.springframework.framework.annotation.GComponentScan
     * */
    public static Set<GangAnnotationAttributes> attributesForRepeatable(GangAnnotationMetadata metadata, String containerClassName, String annotationClassName){

        Set<GangAnnotationAttributes> result = new LinkedHashSet<>();
        //metadata -> StandardAnnotationMetadata 实例
        addAttributesIfNotNull(result, metadata.getAnnotationAttribute(annotationClassName));

        return Collections.unmodifiableSet(result);
    }

    /**
     * 为什么工具类里的方法都是静态方案？
     * */
    private static void addAttributesIfNotNull(Set<GangAnnotationAttributes> result, Map<String, Object> attributes){
        if (attributes != null) {
            result.add(GangAnnotationAttributes.fromMap(attributes));
        }
    }

    static GangBeanDefinitionHolder applyScopedProxyMode(GangScopeMetadata metadata, GangBeanDefinitionHolder definitionHolder, GangBeanDefinitionRegistry registry)
    {
        //TODO
        return definitionHolder;
    }


}
